﻿/*
===========================================================================
Immemorsion LGPL Source code
Copyright trszdev - rahimyanov@gmail.com

This file is part of Immemorsion.

Immemorsion is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Immemorsion is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Immemorsion.  If not, see <http://www.gnu.org/licenses/>.
===========================================================================
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Collections;

namespace Immemorsion
{


    public class ByteMemoryPattern : IByteMemoryPattern
    {
        delegate bool ByteCompareDelegate(byte a, byte b);

        private readonly MaskedByte[] Pattern;
        private Tuple<byte, ByteCompareDelegate>[] SimplifiedPattern;

        private static ByteCompareDelegate MaskToDelegate(ByteMask mask)
        {
            switch (mask)
            {
                case ByteMask.Exact:
                    return (a, b) => a == b;
                case ByteMask.Higher:
                    return (a, b) => a < b;
                case ByteMask.Lower:
                    return (a, b) => a > b;
            }
            return (a, b) => true;
        }

        public MaskedByte this[int index]
        {
            get { return Pattern[index]; }
        }

        public int Count
        {
            get { return Pattern.Length; }
        }

        public IEnumerator<MaskedByte> GetEnumerator()
        {
            for (int i = 0; i < Pattern.Length; i++)
                yield return Pattern[i];
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            var result = this.GetEnumerator();
            return result;
        }

        public ByteMemoryPattern(MaskedByte[] pattern)
        {
            Pattern = pattern;
            SimplifiedPattern = Pattern
               .Select(a => new Tuple<byte, ByteCompareDelegate>
                   (a.Byte, MaskToDelegate(a.ByteMask)))
               .ToArray();
        }

        public virtual bool Suits(byte[] bytes)
        {
            for (int i = 0; i < Pattern.Length; i++)
            {
                var patternTuple = SimplifiedPattern[i];
                var firstByte = patternTuple.Item1;
                var secondByte = bytes[i];
                var success = patternTuple.Item2(firstByte, secondByte);
                if (!success) return false;
            }
            return true;
        }

        public virtual unsafe bool Suits(byte* bytePointer)
        {
            for (int i = 0; i < Pattern.Length; i++)
            {
                var patternTuple = SimplifiedPattern[i];
                var firstByte = patternTuple.Item1;
                var secondByte = *(bytePointer + i);
                var success = patternTuple.Item2(firstByte, secondByte);
                if (!success) return false;
            }
            return true;
        }
    }
}